package com.goldman.aplt.util;

import com.fasterxml.jackson.databind.JsonNode;
import com.goldman.aplt.base.constant.ApConstants;
import com.goldman.aplt.base.exception.BankBusiException;
import com.goldman.aplt.base.type.BaseEnumType;
import com.goldman.aplt.base.type.CmErrorCode;
import com.goldman.aplt.service.packet.ApsOutLogService;
import com.goldman.aplt.service.parameter.AppSystemParameterService;
import com.goldman.http.common.s2s.S2SOption;
import com.goldman.http.common.s2s.S2SResponse;
import com.goldman.http.common.s2s.model.HeaderConstants;
import com.goldman.http.common.s2s.util.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@Component
public class EncryUtil {

    @Autowired
    @Qualifier("appSystemParameterService")
    private AppSystemParameterService appSystemParameterServiceImpl;
    private static AppSystemParameterService appSystemParameterService;

    @PostConstruct
    public void init() {
        appSystemParameterService = appSystemParameterServiceImpl;
    }


    public static String encry(String value, BaseEnumType.E_ENCRY_TYPE type) {
        //如果是type开头的数据， 说明已经加密过了， 直接原值返回
        if (value.startsWith(type.getValue())) {
            return value;
        }
        Map<String, String> resultMap = commEncry(type, BaseEnumType.E_ENCRYPTION.ENCODE, value);
        return resultMap.get(value);
    }

    public static String decry(String value, BaseEnumType.E_ENCRY_TYPE type) {
        //如果不是type开头的数据， 说明没有加密过， 直接原值返回
        if (!value.startsWith(type.getValue())) {
            return value;
        }
        Map<String, String> resultMap = commEncry(type, BaseEnumType.E_ENCRYPTION.DECODE, value);
        return resultMap.get(value);
    }

    public static Map<String, String> encry(String[] values, BaseEnumType.E_ENCRY_TYPE type) {
        return commEncry(type, BaseEnumType.E_ENCRYPTION.ENCODE, values);
    }

    public static Map<String, String> decry(String[] values, BaseEnumType.E_ENCRY_TYPE type) {
        return commEncry(type, BaseEnumType.E_ENCRYPTION.DECODE, values);
    }

    /**
     * 加密解密， 支持多个
     *
     * @param type
     * @param encryption
     * @param keys
     * @return
     */
    private static Map<String, String> commEncry(BaseEnumType.E_ENCRY_TYPE type, BaseEnumType.E_ENCRYPTION encryption, String... keys) {
        Map<String, String> resultMap = new HashMap<>();
        String kycAppId = appSystemParameterService.getValue(ApConstants.KYC, ApConstants.APP_ID);
        String kycAppSecret = appSystemParameterService.getValue(ApConstants.KYC, ApConstants.APP_SECRECT);

        String callSeqNo = ApSeqUtil.genSeq(ApConstants.CALL_SEQ_CODE);

        S2SOption s2sOption = S2SOption.builder().build();
        Map<String, String> headers = new HashMap<>();
        headers.put(HeaderConstants.REQUEST_ID_HEADER, callSeqNo);
        headers.put(HeaderConstants.APP_ID, kycAppId);
        headers.put(HeaderConstants.TOKEN_HEADER, TokenUtil.generateKycRequestToken(kycAppId + kycAppSecret + headers.get(HeaderConstants.REQUEST_ID_HEADER)));
        headers.put(HeaderConstants.UID_HEADER, CommUtil.getTrxnEnvs().getApp_uid());
        headers.put(HeaderConstants.DEVICE_ID_HEADER, CommUtil.getTrxnEnvs().getHeader().getDeviceId());
        s2sOption.setHeaders(headers);

        Map<String, Object> requestBody = new HashMap<>();
        Map<String, Object> content = new HashMap<>();
        content.put("keys", keys);
        content.put("type", type.getValue());

        requestBody.put(ApConstants.DATA, content);

        String url = appSystemParameterService.getValue(ApConstants.ENCRYPTION, encryption.getValue());
        S2SResponse<String> response = HttpUtil.post(url, JsonUtil.toJsonStr(requestBody), callSeqNo, s2sOption);
        int code = response.getResponseData().getStatus().getCode();

        if (code == 4) {
            //NotFound， 原值返回
            for (String key : keys) {
                resultMap.put(key, key);
            }
            return resultMap;
        }

        if (code != 0) {
            throw new BankBusiException(CmErrorCode.ENCRYPTION_ERROR);
        }
        String respStr = JsonUtil.toJsonStr(response.getResponseData().getData());
        JsonNode jsonNode = JsonUtil.toTree(respStr);
        for (String key : keys) {
            String encryValue = JsonNodeUtil.toString(jsonNode.get(key));
            if (StringUtils.isBlank(encryValue)) {
                encryValue = key;
            }
            resultMap.put(key, encryValue);
        }

        return resultMap;
    }
}
